#ifndef _csString_h_
#define _csString_h_

/********************************************************************
	created:	2009/11/27
	created:	27:11:2009   10:21
	filename: 	e:\CrazySprite\code\src\cscorelib\csString.h
	file path:	e:\CrazySprite\code\src\cscorelib
	file base:	csString
	file ext:	h
	author:		dongchengok
	
	purpose:	fuck the string template
*********************************************************************/
#include "csType.h"
#include "csBuffer.h"

//------------------------------------------------------------------------
void	csMemCpy(c8* dst, const c8* src, s32 n);
void	csMemCpy(c16* dst, const c16* src, s32 n);
void	csMemCpy(c32* dst, const c32* src, s32 n);
s32		csStrLen(const c8* s);
s32		csStrLen(const c16* s);
s32		csStrLen(const c32* s);
void	csMemSet(c8* dst, c8 ch, s32 len);
void	csMemSet(c16* dst, c16 ch, s32 len);
void	csMemSet(c32* dst, c32 ch, s32 len);
s32		csStrCmp(const c8* lhs, const c8* rhs);
s32		csStrCmp(const c16* lhs, const c16* rhs);
s32		csStrCmp(const c32* lhs, const c32* rhs);
s32		csStrCaseCmp(const c8* lhs,const c8* rhs);
s32		csStrCaseCmp(const c16* lhs,const c16* rhs);
s32		csStrCaseCmp(const c32* lhs, const c32* rhs);
c8		csToLower(c8 ch);
c16		csToLower(c16 ch);
c32		csToLower(c32 ch);
c8		csToUpper(c8 ch);
c16		csToUpper(c16 ch);
c32		csToUpper(c32 ch);
s32		csVsnprintf(c8* buf, s32 count, const c8* format, va_list args );
s32		csVsnprintf(c16* buf, s32 count, const c16* format, va_list args );
s32		csVsnprintf(c32* buf, s32 count, const c32* format, va_list args);
s32		csMemCmp(const c8* sz1, const c8* sz2, s32 len);
s32		csMemCmp(const c16* sz1, const c16* sz2, s32 len);
s32		csMemCmp(const c32* sz1, const c32* sz2, s32 len);
c8*		csMemChr(const c8* sz1, c8 ch, s32 count);
c16*	csMemChr(const c16* sz1, c16 ch, s32 count);
c32*	csMemChr(const c32* sz1, c32 ch, s32 count);


//------------------------------------------------------------------------
template<typename T>
class csStringBase
{
	friend class csStringHelper;
	struct Rep
	{
		T*					getData();
		const T*			getData() const;
		T*					refCopy();
		s32					getSize() const;
		void				unRef();
		void				freeMemory();
		Rep*				clone() const;
		static Rep*			Create(s32 slen);
		s32 m_length;
		s32 m_capacity;
		s32 m_references;
	};
public:
	csStringBase();
	csStringBase(const T* str);
	csStringBase(T ch, s32 len);
	csStringBase(const T* str, s32 len);
	csStringBase(const csStringBase<T>& other);
	~csStringBase();

	csStringBase<T>&		operator=(const csStringBase<T>& rhs);
	csStringBase<T>&		operator=(const T* rhs);
	T						operator[](s32 idx) const;

	s32						length() const;
	bool					empty() const;
	void					printf(const T* format, ...);
	void					printfV(const T* format, va_list args);
	const T*				c_str() const;
	void					reserve(s32 n);

	csStringBase<T>			subString(s32 index, s32 num=csINVALID_INDEX) const;
	csStringBase<T>&		remove(s32 idx);
	csStringBase<T>&		remove(s32 idx, s32 len);
	csStringBase<T>&		setChar(s32 idx, T ch);
	void					swap(csStringBase<T>& other);

	s32						find(const csStringBase<T>& str, s32 nStart = 0) const;
	s32						find(const T* sz, s32 nStart = 0, s32 n = csINVALID_INDEX) const;
	s32						find(T ch, s32 nStart = csINVALID_INDEX) const;
	s32						rfind(const csStringBase<T>& str, s32 nStart = csINVALID_INDEX) const;
	s32						rfind(const T* sz, s32 nStart = csINVALID_INDEX,	s32 n = csINVALID_INDEX) const;
	s32						rfind(T ch, s32 nStart = csINVALID_INDEX) const;

	csStringBase<T>&		insert(s32 nPos, const csStringBase<T>& str);
	csStringBase<T>&		insert(s32 nPos, const csStringBase<T>& str, s32 nStart, s32 n);
	csStringBase<T>&		insert(s32 nPos, const T *sz);
	csStringBase<T>&		insert(s32 nPos, const T *sz, s32 n);
	csStringBase<T>&		insert(s32 nPos, s32 n, T ch);

	csStringBase<T>&		replace(s32 idx, s32 n, csStringBase<T>& str);
	csStringBase<T>&		replace(s32 idx, s32 n, csStringBase<T>& str, s32 sidx, s32 sn);
	csStringBase<T>&		replace(s32 idx, s32 n, const T* str);
	csStringBase<T>&		replace(s32 idx, s32 n, const T* str, s32 sidx, s32 sn);
	csStringBase<T>&		replace(s32 idx, s32 n, T ch, s32 cn);

	csStringBase<T>&		append(const csStringBase<T>& str);
	csStringBase<T>&		append(const csStringBase<T>& str, s32 idx, s32 n);
	csStringBase<T>&		append(const T* str);
	csStringBase<T>&		append(const T* str, s32 idx, s32 n);
	csStringBase<T>&		append(T ch, s32 n);

	s32						compare(const csStringBase<T>& other) const;
	s32						compare(const T* other) const;
	s32						compareIgnoreCase(const csStringBase<T>& other) const;
	s32						compareIgnoreCase(const T* other) const;

	bool					beginsWith(const csStringBase<T>& s) const;
	bool					beginsWith(const T* s) const;
	bool					endsWith(const csStringBase<T>& s) const;
	bool					endsWith(const T* s) const;

	csStringBase<T>&		asLower();
	csStringBase<T>&		asUpper();

	bool					operator==(const csStringBase<T>& rhs) const;
	bool					operator==(const T* rhs) const;
	bool					operator!=(const csStringBase<T>& rhs) const;
	bool					operator!=(const T* rhs) const;
	bool					operator> (const csStringBase<T>& rhs) const;
	bool					operator>=(const csStringBase<T>& rhs) const;
	bool					operator< (const csStringBase<T>& rhs) const;
	bool					operator<=(const csStringBase<T>& rhs) const;
	csStringBase<T>			operator +(const csStringBase<T>& rhs) const;
	csStringBase<T>			operator +(const T* rhs) const;
	csStringBase<T>			operator +(T ch) const;
	csStringBase<T>&		operator+=(const csStringBase<T>& str);
	csStringBase<T>&		operator+=(const T* str);
	csStringBase<T>&		operator+=(T ch);

public:
	static csStringBase<T>	Format(const T* format, ...);

protected:	
	explicit				csStringBase(Rep* r);
	Rep&					_getRep() const;
	T*						m_string;
	static u8				ms_emptyStringRep[sizeof(s32)+sizeof(s32)+sizeof(s32)+sizeof(T)];
	static Rep&				_GetEmptyStringRep();
};


typedef csStringBase<c8>	csCString;
typedef csStringBase<c16>	csWString;
typedef csStringBase<c32>	csDisplayString;

#ifdef _UNICODE
typedef csWString			csString;
#else
typedef csCString			csString;
#endif

//------------------------------------------------------------------------
//string converter
//------------------------------------------------------------------------
class csStringHelper
{
public:
	static csCString		Unicode32ToAnsi(const csDisplayString& ustr);
	static csCString		Utf16ToAnsi(const csWString& wstr);
	static csCString		Utf8ToAnsi(const csCString& utf);

	static csCString		Unicode32ToUtf8(const csDisplayString& ustr);
	static csCString		Utf16ToUtf8(const csWString& wstr);
	static csCString		AnsiToUtf8(const csCString& ansi);

	static csWString		Unicode32ToUtf16(const csDisplayString& ustr);
	static csWString		Utf8ToUtf16(const csCString& utf8);
	static csWString		AnsiToUtf16(const csCString& ansi);

	static csDisplayString	Utf16ToUnicode32(const csWString& wstr);
	static csDisplayString	Utf8ToUnicode32(const csCString& utf8);
	static csDisplayString	AnsiToUnicode32(const csCString& ansi);
};

#include "csString.inl"

#endif // _csString_h_